/**
 * Class VApplication - write a description of the class here 
 * This is a program designed to be used in the voting for superlatives by the senior class of 
 * Half Hollow Hills High School West
 * Creator: Azaria Zornberg
 * Designer: Azaria Zornberg
 * Project Supervisor: Matthew Maroney
 * Localized Version - created for the class of 2012 and 2013
 */

import java.awt.*;
import javax.swing.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;
import java.util.ArrayList;
import java.util.TreeSet;
import java.util.Scanner;
import java.io.*;
public class VApplication
{
    public static void main(String[] args){
        VApplication votingBooth = new VApplication();
        votingBooth.start();
    }    

    JFrame frame = new JFrame("Senior Superlatives");
    Dimension screenSize = new Dimension(960, 700);
    ArrayList<String> categories = new ArrayList();
    ArrayList<Voter> students = new ArrayList();
    ArrayList<String> males = new ArrayList();
    ArrayList<String> females = new ArrayList();
    JComboBox names;
    JComboBox[] mSuperlatives, fSuperlatives;
    JLabel[] catNames;
    JButton enterVote;
    Voter currentVoter, attempt;

    public void start()
    {
        // this method begins the running of the program
        frame.setVisible(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(screenSize);
        readInData();
        checkId();
    }
    
    public void restart(){
        frame.setVisible(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(screenSize);
        resetScreen();
        checkId();
    }
    
    public void readInData(){
        //this method reads in all of the data necessary for the program
        //it stores all of the category names in one arraylist, all the id numbers of students in alphabetical order in another
        //and it stores all of the guys and girls in alphabetical order by last name in 2 separate arraylists
        //last, first format for names
        try{
            Scanner cats = new Scanner(new File("Categories.txt"));
            Scanner studs = new Scanner(new File("ID.txt"));
            Scanner femaleRead = new Scanner(new File("Females.txt"));
            Scanner maleRead = new Scanner(new File("Males.txt"));
            ArrayList<String> tempMales = new ArrayList();
            ArrayList<String> tempFemales = new ArrayList();
            ArrayList<Voter> tstudents = new ArrayList();
            while(cats.hasNextLine()){
                categories.add(cats.nextLine());
            }
            cats.close();
            
            while(femaleRead.hasNextLine()){
                String fInput = femaleRead.nextLine();
                String[] fParts = fInput.split("\t");
                String fName = fParts[0] + ", " + fParts[1];
                tempFemales.add(fName);
            }
            females = new ArrayList(tempFemales.size());
            for(String s: tempFemales){
                females.add(s);
            }
            
            femaleRead.close();
            
            while(maleRead.hasNextLine()){
                String mInput = maleRead.nextLine();
                String[] mParts = mInput.split("\t");
                String mName = mParts[0] + ", " + mParts[1];
                tempMales.add(mName);
            }
            males = new ArrayList(tempMales.size());
            for(String s: tempMales){
                males.add(s);
            }
            
            maleRead.close();
            
            while(studs.hasNextLine()){
                String input = studs.nextLine();
                String name = "";
                if(tempFemales.size() > 0){
                    name = tempFemales.remove(0);
                }else{
                    name = tempMales.remove(0);
                }
                Voter v = new Voter(name, input);
                tstudents.add(v);
            }
            
            students = new ArrayList(tstudents.size());
            for(Voter transfer: tstudents){
                students.add(transfer);
            }
            
            studs.close();
            
        }catch(IOException e){
            System.err.println("File Error Encountered. Please File a Report.");
            System.exit(1);
        }
        
    }
    
    public void checkId(){
        //this will verify that the student exists in the database of students in the school
        String[] allStuds = new String[males.size() + females.size()];
        for(int n = 0; n < students.size(); n++){
            allStuds[n] = students.get(n).getName();
        }
        LoginWindow login = new LoginWindow(allStuds);
    }
    
    public void resetScreen(){
        for(int i = 0; i < mSuperlatives.length; i++){
            mSuperlatives[i].setSelectedIndex(0);
            fSuperlatives[i].setSelectedIndex(0);
        }
    }
    
    public void loginSuccessful(){
        //this method proceeds to run the rest of the program and allow the student to vote if their login is verified
        frame.setVisible(true);
        initializeComponents();
        placeComponents();
        restoreVotes();
    }
    
    public void secondLogin(){
        frame.setVisible(true);
        restoreVotes();
        frame.setSize(1150, 60 * (catNames.length/2 + 2));
        enterVote.setBounds(525, frame.getHeight()-100, 100, 30);
        frame.setResizable(false);
        JButton dummy = new JButton();
        dummy.setVisible(false);
        frame.add(dummy);
    }
    
    public void initializeComponents(){
        //this method initializes all the components that will be put into the window
        //it creates the combo boxes that will be used for selecting guys and girls for each category
        //it also places the labels with category names and the button for voting
        mSuperlatives = new JComboBox[categories.size()];
        fSuperlatives = new JComboBox[categories.size()];
        String[] guys, girls;
        guys = new String[males.size() + 1];
        girls = new String[females.size() + 1];
        
        girls[0] = "No Vote";
        guys[0] = "No Vote";
        for(int i = 1; i < females.size() + 1; i++){
            girls[i] = females.get(i-1);
        }
        
        for(int c = 1; c < males.size() + 1; c++){
            guys[c] = males.get(c-1);
        }
        
        for(int x = 0; x < categories.size(); x++){
            mSuperlatives[x] = new JComboBox(guys);
            fSuperlatives[x] = new JComboBox(girls);
            mSuperlatives[x].setBackground((Color.yellow));
            mSuperlatives[x].setForeground(Color.black);
            fSuperlatives[x].setBackground((Color.yellow));
            fSuperlatives[x].setForeground(Color.black);
        }
        
        catNames = new JLabel[categories.size()];
        enterVote = new JButton("Cast Vote");
        enterVote.setBackground((Color.yellow));
        frame.getContentPane().setBackground(Color.red);
    }
    
    public void placeComponents(){
        //this method places the components in the window. it makes even columns on each side of the window
        //the window is then sized appropriately
        JLabel m1, m2, f1, f2;
        m1 = new JLabel("Male");
        m2 = new JLabel("Male");
        f1 = new JLabel("Female");
        f2 = new JLabel("Female");
        m1.setForeground(Color.yellow);
        m2.setForeground(Color.yellow);
        f1.setForeground(Color.yellow);
        f2.setForeground(Color.yellow);
        
        int yInterval = 50;
        for(int n = 0; n < categories.size(); n++){
            catNames[n] = new JLabel("<html><p>" + categories.get(n) + "</p></html>");
        }
        
        for(int r = 0; r < catNames.length/2; r++){
            frame.add(catNames[r]);
            catNames[r].setBounds(5, yInterval*(1 + r) + 10, 150, 40);
            catNames[r].setForeground(Color.yellow);
            frame.add(mSuperlatives[r]);
            mSuperlatives[r].setBounds(180, yInterval*(1 + r) + 10, 150, 25);
            frame.add(fSuperlatives[r]);
            fSuperlatives[r].setBounds(355, yInterval*(1 + r) + 10, 150, 25);
        }
        
        for(int l = catNames.length - 1; l > catNames.length/2 - 1; l--){
            frame.add(catNames[l]);
            catNames[l].setBounds(600, yInterval*(catNames.length - l) + 10, 150, 40);
            catNames[l].setForeground(Color.yellow);
            frame.add(mSuperlatives[l]);
            mSuperlatives[l].setBounds(775, yInterval*(catNames.length - l) + 10, 150, 25);
            frame.add(fSuperlatives[l]);
            fSuperlatives[l].setBounds(950, yInterval*(catNames.length - l) + 10, 150, 25);
        }
        
        frame.add(m1);
        frame.add(m2);
        frame.add(f1);
        frame.add(f2);
        m1.setBounds(180, 10, 50, 30);
        m2.setBounds(775, 10, 50, 30);
        f1.setBounds(355, 10, 50, 30);
        f2.setBounds(950, 10, 50, 30);
        
        frame.add(enterVote);
        frame.setSize(1150, 60 * (catNames.length/2 + 2));
        enterVote.setBounds(525, frame.getHeight()-100, 100, 30);
        enterVote.addActionListener(new VoteListener());
        enterVote.addChangeListener(new VChangeListener());
        frame.setResizable(false);
        JButton dummy = new JButton();
        dummy.setVisible(false);
        frame.add(dummy);
    }
    
    public void restoreVotes(){
        String name = currentVoter.getID() + ".txt";
        File currentV = new File(name);
        if(!currentV.exists()){
            return;
        }
        try{
            Scanner vReader = new Scanner(currentV);
            String mV[] = vReader.nextLine().split(";");
            String fV[] = vReader.nextLine().split(";");
            
            for(int i = 0; i < mSuperlatives.length; i++){
                mSuperlatives[i].setSelectedItem(mV[i]);
                fSuperlatives[i].setSelectedItem(fV[i]);
            }
        }catch(IOException e){
            System.err.println("looks like I screwed up somewhere. oh well");
        }
    }
    
    public void castVote(){
        //this is the castVote method. it reads in the people chosen in the window for each category and 
        //records the votes to be written to a file
        String mVotes[] = new String[mSuperlatives.length];
        String fVotes[] = new String[fSuperlatives.length];
        for(int i = 0; i < mVotes.length; i++){
            mVotes[i] = (String) mSuperlatives[i].getSelectedItem();
            fVotes[i] = (String) fSuperlatives[i].getSelectedItem();
        }
        try{
            writeData(currentVoter.getID(), mVotes, fVotes);
        }catch (IOException e){
            System.err.println("Writing error");
        }
    }
    
    public void writeData(String myID, String[] mVotes, String[] fVotes) throws IOException{
        //this method will write the vote data for a vote cast to a file
        //it makes the file name the id number of the student who cast the vote.
        //it also makes the file read only
        File f = new File(myID + ".txt");
        if(!f.createNewFile()){
            f.delete();
            f.createNewFile();
        } 
        String maleNames = "";
        String femaleNames = "";
        for(String name: mVotes) {
            maleNames += name + ";";
        }
        maleNames = maleNames.substring(0, maleNames.lastIndexOf(";"));
        for(String name: fVotes) {
            femaleNames += name + ";";
        }
        femaleNames = femaleNames.substring(0, femaleNames.lastIndexOf(";"));
        FileWriter fstream = new FileWriter(f);
        BufferedWriter out = new BufferedWriter(fstream);
        out.write(maleNames);
        out.newLine();
        out.write(femaleNames);
        out.close();
        f.setReadOnly();
    }
    
    public class VoteListener implements ActionListener
    {
        VoteListener(){
            super();
        }
        
        public void actionPerformed(ActionEvent e){
            //this method is called when the button is pressed to cast the student's vote
            //it asks to make sure they wish to cast their vote. it does nothing if they respond no, and calls castVote() if they say yes
            int n = JOptionPane.showConfirmDialog(null, "Are you sure you wish to cast this vote?", "Cast Vote?", JOptionPane.YES_NO_OPTION);
            if(n < 1){
                castVote();
                frame.setVisible(false);
                restart();
            }
        }
    }
    
    public class VChangeListener implements ChangeListener
    {
        public void stateChanged(ChangeEvent e){
            //this method detects when the button for casting votes has changed size or position and corrects it
            enterVote.setBounds(525, frame.getHeight()-100, 100, 30);
        }
    }
    
    
    public class LoginWindow extends JFrame
    {
        //this is the LoginWindow class, it's used by students to validate their name and id number to log in
        JComboBox allStudents;
        JTextField password = new JTextField();
        JButton login = new JButton("Login");
        JLabel l = new JLabel("Name:");
        JLabel pass = new JLabel("ID Number:");
        String id, name;
        int tries;
    
        LoginWindow(String[] names){
            //this is the login window constructor, it sets up the defaults for the login window
            super("Login");
            allStudents = new JComboBox(names);
            setSize(400, 250);
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
            add(allStudents);
            allStudents.setBounds(125, 20, 250, 40);
            allStudents.setBackground(Color.yellow);
        
            add(l);
            l.setBounds(10, 20, 100, 40);
            l.setForeground(Color.yellow);
        
            add(pass);
            pass.setBounds(10, 100, 100, 30);
            pass.setForeground(Color.yellow);
            
            add(password);
            password.setBounds(125, 100, 250, 40);
            password.setBackground(Color.yellow);
        
            add(login);
            login.setBounds(50, 150, 300, 50);
            login.addActionListener(new LoginListener());
            login.addChangeListener(new LChangeListener());
            login.setBackground(Color.yellow);
            JButton dummy = new JButton();
            dummy.setVisible(false);
            add(dummy);
            setVisible(true);
            getContentPane().setBackground(Color.red);
        }
    
        public void checkValid(){
            //this method checks to make sure the name and id number given by the student are correct
            //if 3 unsuccessful attempts are made at logging in, the system shuts down
            attempt = new Voter(name, id);
            if(students.contains(attempt)){
                setVisible(false);
                currentVoter = attempt;
                if(mSuperlatives != null){
                    resetScreen();
                    secondLogin();
                    return;
                }
                loginSuccessful();
            }else{
                if(tries == 2){
                    JOptionPane.showMessageDialog(this, "Too many incorect attempts have been made. System shutting down.");
                    setVisible(false);
                    System.exit(1);
                }else{
                    tries++;
                    JOptionPane.showMessageDialog(this, "Incorrect name and id number combination. Please try again.");
                }
            }
        }
    
        public class LoginListener implements ActionListener
        {
            LoginListener(){
            }
        
            public void actionPerformed(ActionEvent e){
                //this method reads in the id number and name chosen by the student when they press the button to login
                id = password.getText();
                name = (String) allStudents.getSelectedItem();
                checkValid();
            }
        }
    
        public class LChangeListener implements ChangeListener
        {
            //this is a login change listener. it corrects the button size every time it tries to change
            public void stateChanged(ChangeEvent e){
                login.setBounds(50, 150, 300, 50);
            }
        }
    }

}